package com.sybil.spa.servicio;

import com.sybil.spa.dao.SolicitudDAO;
import com.sybil.spa.dominio.CorreoSolicitud;
import com.sybil.spa.dominio.DetalleSolicitud;
import com.sybil.spa.dominio.Evento;
import com.sybil.spa.dominio.Flujo;
import com.sybil.spa.dominio.Paso;
import com.sybil.spa.dominio.Responsable;
import com.sybil.spa.dominio.Solicitud;
import com.sybil.spa.dominio.Usuario;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("solicitudServicio")
@Transactional(readOnly = true)
public class SolicitudServicio {

   @Autowired
   private SolicitudDAO solicitudDAO;
   @Autowired
   private FlujoServicio flujoServicio;
   @Autowired
   private EmailServicio emailServicio;

   public void guardar(Solicitud solicitud) {
      solicitudDAO.guardarSolicitud(solicitud);
   }

   public void editar(Solicitud solicitud) {
      solicitudDAO.editarSolicitud(solicitud);
   }

   @Transactional(readOnly = false)
   public void eliminarSolicitud(String claveFlujo, int numero) {
      Solicitud solicitud = solicitudDAO.getSolicitud(claveFlujo, numero);
      solicitudDAO.eliminarSolicitud(solicitud);
   }

   public List<Solicitud> obtenerSolicitudes() {
      return solicitudDAO.getSolicitudes();
   }

   public List<Solicitud> obtenerSolicitudes(String claveUsuario) {
      List<Solicitud> solicitudes = solicitudDAO.getSolicitudes(claveUsuario);
      for (Solicitud solicitud : solicitudes) {
         List<DetalleSolicitud> detalles = solicitud.getDetalles();
         for (DetalleSolicitud detalle : detalles) {
            detalle.setUsuario(flujoServicio.getUsuario(detalle.getClaveUsuario()));
         }
      }
      return solicitudes;
   }

   public List<Solicitud> obtenerHistorico(String claveFlujo, String fechaDesde, String fechaHasta,
           String estatus, String numeroSolicitud) {
      int numero = 0;
      final DateFormat soloFecha = new SimpleDateFormat("dd/MM/yyyy");
      Date fecha1 = null, fecha2 = null;
      try {
         fecha1 = soloFecha.parse(fechaDesde);
         fecha2 = soloFecha.parse(fechaHasta);
         long fin = fecha2.getTime();
         fin += 82800000 + 3540000 + 59000;//se se garegan 23 horas 59 min, 59 seg
         fecha2.setTime(fin);
      } catch (ParseException ex) {
         fecha1 = null;
         fecha2 = null;
      }
      try {
         numero = Integer.parseInt(numeroSolicitud);
      } catch (NumberFormatException ex) {
         numero = 0;
      }
      List<Solicitud> historico = solicitudDAO.getHistorico(claveFlujo, fecha1, fecha2, estatus, numero);
      for (Solicitud solicitud : historico) {
         List<DetalleSolicitud> detalles = solicitud.getDetalles();
         for (DetalleSolicitud detalle : detalles) {
            detalle.setUsuario(flujoServicio.getUsuario(detalle.getClaveUsuario()));
         }
      }
      return historico;
   }

   public Solicitud obtenerSolicitud(String claveFlujo, int numero) {
      Solicitud solicitud = solicitudDAO.getSolicitud(claveFlujo, numero);
      List<DetalleSolicitud> detalles = solicitud.getDetalles();
      for (DetalleSolicitud detalle : detalles) {
         detalle.setUsuario(flujoServicio.getUsuario(detalle.getClaveUsuario()));
         List<CorreoSolicitud> correos = detalle.getCorreos();
         for (CorreoSolicitud correo : correos) {
            correo.setUsuario(flujoServicio.getUsuario(correo.getClaveUsuario()));
         }
      }
      return solicitud;
   }

   public Solicitud aprobarSolicitud(String claveFlujo, int numeroSolicitud, String claveUsuario,
           String claveEvento, String comentarios) {
      Solicitud solicitud = solicitudDAO.getSolicitud(claveFlujo, numeroSolicitud);
      Paso pasoActual = solicitud.getPaso();
      int aprobadores = 1;//inicia en 1 porque cuenta el aprobador actual
      int aprobadoresForsozos = 1;//inicia en 1 porque cuenta el aprobador actual
      Evento eventoAejecutar = null;
      Paso pasoInicial = null;
      Paso pasoSigue = null;
      Usuario solicitante = null;
      List<Evento> eventos = pasoActual.getEventos();
      for (Evento even : eventos) {
         if (even.getLlave().getClaveEvento().equals(claveEvento)) {
            eventoAejecutar = even;
         }
      }
      List<DetalleSolicitud> detallesSolicitud = solicitud.getDetalles();
      List<DetalleSolicitud> detallesPaso = new ArrayList<DetalleSolicitud>();
      int numeroSiguienteDetalle = detallesSolicitud.size() + 1;
      for (DetalleSolicitud detalle : detallesSolicitud) {
         if ("I".equals(detalle.getEvento().getPaso().getTipo()) && detalle.getInstancia() == 1) {
            solicitante = flujoServicio.getUsuario(detalle.getClaveUsuario());
            pasoInicial = detalle.getEvento().getPaso();
         }
         if (detalle.getInstancia() == solicitud.getInstancia()) {
            if (pasoActual.equals(detalle.getEvento().getPaso())) {
               detallesPaso.add(detalle);
            }
         }
      }
      List<Responsable> responsables = pasoActual.getResponsables();
      boolean haVotado = false;
      boolean esAprobadorPasoActual = false;
      for (DetalleSolicitud detalle2 : detallesPaso) { //detalles de la solicitud del paso actual
         if ("N".equals(pasoActual.getJerarquico())) {
            for (Responsable responsable : responsables) {//responsables del paso actual
               if ("S".equals(responsable.getEsAprobador())) {//si el responsable del paso es aprobador
                  if ("S".equals(responsable.getForzoso())) {
                     if (detalle2.getClaveUsuario().equals(responsable.getLlave().getClaveUsuario())) {
                        aprobadoresForsozos++;
                     }
                  } else if (detalle2.getClaveUsuario().equals(responsable.getLlave().getClaveUsuario())) {
                     aprobadores++;
                  }
                  if (responsable.getLlave().getClaveUsuario().equals(claveUsuario)) {
                     esAprobadorPasoActual = true;// es responsable del paso actual
                  }
               }
            }
         } else { //cuando el paso es jerarquico cualquier puede ser responsable
            esAprobadorPasoActual = true;
         }
         if (esAprobadorPasoActual) {
            if (detalle2.getClaveUsuario().equals(claveUsuario)) {
               haVotado = true;// ya ha ejercido su voto.
            }
         }
      }

      if (eventoAejecutar != null && !haVotado) {
         if ("S".equals(pasoActual.getJerarquico())) {
            for (Responsable responsable : responsables) {
               if (claveUsuario.equals(responsable.getLlave().getClaveUsuario())) { //es el ultimo aprobador
                  if ("S".equals(solicitud.getFlujo().getValidaMonto()) && solicitud.getMontoSolicitud() <= pasoActual.getMontoAprobacion()
                          && eventoAejecutar.getPasoSiguienteMonto() != null) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               }
            }
            if (pasoSigue == null) {
               pasoSigue = pasoActual;
            }
         } else { //el paso no es jerarquico
            if ("U".equals(eventoAejecutar.getTipoAprobacion())) {//aprobacion unica
               if ("S".equals(solicitud.getFlujo().getValidaMonto()) && solicitud.getMontoSolicitud() <= pasoActual.getMontoAprobacion()
                       && eventoAejecutar.getPasoSiguienteMonto() != null) {
                  pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
               } else {
                  pasoSigue = eventoAejecutar.getPasoSiguiente();
               }
            } else if ("N".equals(eventoAejecutar.getTipoAprobacion())) { //aprobacion numerica
               if ("S".equals(eventoAejecutar.getValidaForzosos())) {
                  if (aprobadoresForsozos == eventoAejecutar.getNumeroAprobadores()) {
                     if ("S".equals(solicitud.getFlujo().getValidaMonto()) && solicitud.getMontoSolicitud() <= pasoActual.getMontoAprobacion()
                             && eventoAejecutar.getPasoSiguienteMonto() != null) {
                        pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                     } else {
                        pasoSigue = eventoAejecutar.getPasoSiguiente();
                     }
                  } else {
                     pasoSigue = pasoActual;
                  }
               } else if (aprobadores == eventoAejecutar.getNumeroAprobadores()) {
                  if ("S".equals(solicitud.getFlujo().getValidaMonto()) && solicitud.getMontoSolicitud() <= pasoActual.getMontoAprobacion()
                          && eventoAejecutar.getPasoSiguienteMonto() != null) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               } else {
                  pasoSigue = pasoActual;
               }
            } else { //todos aprueban
               if ("S".equals(eventoAejecutar.getValidaForzosos())) {
                  if (aprobadoresForsozos == responsables.size()) {
                     if ("S".equals(solicitud.getFlujo().getValidaMonto()) && solicitud.getMontoSolicitud() <= pasoActual.getMontoAprobacion()
                             && eventoAejecutar.getPasoSiguienteMonto() != null) {
                        pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                     } else {
                        pasoSigue = eventoAejecutar.getPasoSiguiente();
                     }
                  } else {
                     pasoSigue = pasoActual;
                  }
               } else if (aprobadores == responsables.size()) {
                  if ("S".equals(solicitud.getFlujo().getValidaMonto()) && solicitud.getMontoSolicitud() <= pasoActual.getMontoAprobacion()
                          && eventoAejecutar.getPasoSiguienteMonto() != null) {
                     pasoSigue = eventoAejecutar.getPasoSiguienteMonto();
                  } else {
                     pasoSigue = eventoAejecutar.getPasoSiguiente();
                  }
               } else {
                  pasoSigue = pasoActual;
               }
            }
         }

         if (pasoSigue != null) {
            solicitud.setPaso(pasoSigue);
            solicitud.setUsuarioModif(claveUsuario);
            if ("F".equals(pasoSigue.getTipo())) {
               solicitud.setTerminado("S");
               solicitud.setFinalCorrecto(pasoSigue.getFinalCorrecto());
            }
            DetalleSolicitud detalle = null;
            detalle = new DetalleSolicitud(claveFlujo, numeroSolicitud, numeroSiguienteDetalle);
            detalle.setInstancia(solicitud.getInstancia());
            detalle.setComentarios(comentarios);
            detalle.setEvento(eventoAejecutar);
            detalle.setClaveUsuario(claveUsuario);
            detalle.setUsuario(flujoServicio.getUsuario(claveUsuario));
            detalle.setCausa(null);
            detalle.setUsuarioCreo(claveUsuario);
            detalle.setFecha(new Date());
            List<String> personasAprobaron = new ArrayList<String>();
            personasAprobaron.add(claveUsuario);
            for (DetalleSolicitud detalleX : detallesSolicitud) {
               if (detalleX.getInstancia() == solicitud.getInstancia()) {
                  personasAprobaron.add(detalleX.getClaveUsuario());
                  if (detalleX.getClavePaso().equals(pasoSigue.getLlave().getClavePaso())) {
                     solicitud.setInstancia(solicitud.getInstancia() + 1);
                  }
               }
            }
            if ("S".equals(pasoSigue.getEnviaAviso())) {
               String tipoFlujo = solicitud.getFlujo().getTipo();
               if ("S".equals(pasoSigue.getJerarquico())) {
                  if (detalle.getUsuario().getJefe() != null) {
                     solicitud.setAsignadoA(detalle.getUsuario().getJefe().getClave());
                     pasoSigue.setResponsables(new ArrayList<Responsable>(1));
                     pasoSigue.getResponsables().add(new Responsable(detalle.getUsuario().getJefe()));
                  }
               } else if (pasoSigue.getResponsables().size() == 1) {
                  solicitud.setAsignadoA(pasoSigue.getResponsables().get(0).getLlave().getClaveUsuario());
               } else {
                  solicitud.setAsignadoA("Resp: " + pasoSigue.getResponsables().size());
               }
               for (int p = 0; p < personasAprobaron.size(); p++) {
                  personasAprobaron.set(p, flujoServicio.getNombreUsuario(personasAprobaron.get(p)));
               }
               Collections.reverse(personasAprobaron);
               if ("S".equals(solicitud.getTerminado())) {
                  detalle.setCorreos(notificar(numeroSolicitud, numeroSiguienteDetalle,
                          claveUsuario, solicitante, pasoInicial.getResponsables(), pasoSigue,
                          solicitud.getFecha(), personasAprobaron, tipoFlujo));
               } else {
                  detalle.setCorreos(notificar(numeroSolicitud, numeroSiguienteDetalle,
                          claveUsuario, solicitante, pasoSigue.getResponsables(), pasoSigue,
                          solicitud.getFecha(), personasAprobaron, tipoFlujo));
               }
            }
            solicitud.getDetalles().add(detalle);
         } else {
            //no continua
         }
      } else {
         //el evento no corresponde al paso
      }
//      solicitudDAO.editarSolicitud(solicitud);
      return solicitud;
   }

   public Solicitud generarSolicitud(String claveFlujo, String claveUsuario,
           double montoFlujo, String comentarios) {
      //validar flujo
      Solicitud solicitud = null;
      Flujo flujo = flujoServicio.obtenerFlujo(claveFlujo);
      int numeroSolicitud;
      if (flujo != null) {
         if ("A".equals(flujo.getEstatus())) {
            List<Paso> pasos = flujo.getPasos();
            if (pasos.isEmpty()) {
               numeroSolicitud = 0;
            } else {
               Paso pasoInicial = null;
               for (Paso paso : pasos) {
                  if ("I".equals(paso.getTipo())) {
                     pasoInicial = paso;
                  }
               }
               Evento evento = pasoInicial.getEventos().get(0);
               boolean esResponsable = false;
               if ("N".equals(pasoInicial.getJerarquico())) {
                  List<Responsable> responsables = pasoInicial.getResponsables();
                  for (Responsable responsable : responsables) {
                     if (claveUsuario.equals(responsable.getLlave().getClaveUsuario())) {
                        esResponsable = true;
                     }
                  }
               } else {
                  esResponsable = true;
               }
               if (esResponsable) {
                  Paso pasoSiguiente = evento.getPasoSiguiente();
                  numeroSolicitud = solicitudDAO.getSecuencia(claveFlujo);
                  solicitud = new Solicitud(claveFlujo, numeroSolicitud);
                  solicitud.setPaso(pasoSiguiente);
                  solicitud.setMontoSolicitud(montoFlujo);
                  solicitud.setInstancia(1);
                  solicitud.setTerminado("N");
                  solicitud.setFinalCorrecto("N");
                  solicitud.setUsuarioCreo(claveUsuario);
                  DetalleSolicitud detalle = null;
                  detalle = new DetalleSolicitud(claveFlujo, numeroSolicitud, 1);
                  detalle.setInstancia(1);
                  detalle.setComentarios(comentarios);
                  detalle.setEvento(evento);
                  detalle.setClaveUsuario(claveUsuario);
                  detalle.setUsuario(flujoServicio.getUsuario(claveUsuario));
                  detalle.setCausa(null);
                  detalle.setUsuarioCreo(claveUsuario);
                  solicitud.setFecha(new Date());
                  detalle.setFecha(solicitud.getFecha());
                  List<DetalleSolicitud> detalles = new ArrayList<DetalleSolicitud>();
                  if ("S".equals(pasoSiguiente.getEnviaAviso())) {
                     String tipoFlujo = flujo.getTipo();
                     if ("S".equals(pasoSiguiente.getJerarquico())) {
                        if (detalle.getUsuario().getJefe() != null) {
                           solicitud.setAsignadoA(detalle.getUsuario().getJefe().getClave());
                           pasoSiguiente.setResponsables(new ArrayList<Responsable>(1));
                           pasoSiguiente.getResponsables().add(new Responsable(detalle.getUsuario().getJefe()));
                        }
                     } else if (pasoSiguiente.getResponsables().size() == 1) {
                        solicitud.setAsignadoA(pasoSiguiente.getResponsables().get(0).getLlave().getClaveUsuario());
                     } else {
                        solicitud.setAsignadoA("Resp: " + pasoSiguiente.getResponsables().size());
                     }
                     detalle.setCorreos(notificar(numeroSolicitud, 1,
                             claveUsuario, detalle.getUsuario(), pasoSiguiente.getResponsables(),
                             pasoSiguiente, solicitud.getFecha(), null, tipoFlujo));
                     detalles.add(detalle);
                     solicitud.setDetalles(detalles);
                  }
               }
            }
         } else {
//            numeroSolicitud = 0;
         }
      }
      return solicitud;
   }

   private List<CorreoSolicitud> notificar(int numeroSolicitud, int numeroDetalle, String claveUsuarioCreo,
           Usuario solicitante, List<Responsable> responsablesIni, Paso pasoNotifica,
           Date fechaCreado, List<String> personasAprobaron, String tipoFlujo) {
      List<CorreoSolicitud> correos = new ArrayList<CorreoSolicitud>();
      List<Responsable> responsables;
      CorreoSolicitud correo;
      int contadorCorreos = 0;
      if (pasoNotifica.getTipo().equals("F")) {
         correo = new CorreoSolicitud(pasoNotifica.getFlujo().getClave(),
                 numeroSolicitud, numeroDetalle, ++contadorCorreos);
         correo.setUsuario(solicitante);
         correo.setUsuarioCreo(claveUsuarioCreo);
         if (solicitante.getEmail() != null) {
            correo.setEmail(solicitante.getEmail());
            try {
               String asunto = "Solicitud # " + numeroSolicitud
                       + " Finalizada, Paso: " + pasoNotifica.getDescripcionCorta();
               String mensaje;
               if ("RE".equals(tipoFlujo)) {
                  mensaje = generarMensajeReembolsoFin(solicitante.getNombre(), pasoNotifica.getFlujo().getClave(),
                          pasoNotifica.getFlujo().getDescripcionCorta(),
                          numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                          solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);

               } else {
                  mensaje = generarMensajeFin(solicitante.getNombre(), pasoNotifica.getFlujo().getClave(),
                          pasoNotifica.getFlujo().getDescripcionCorta(),
                          numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                          solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);
               }

               emailServicio.enviarEmailHTML(solicitante.getEmail(), asunto, mensaje);
               correo.setEstatus("E");
            } catch (Exception ex) {
               correo.setEstatus("O");
               correo.setComentarios(ex.getMessage());
            }
         } else {
            correo.setEstatus("O");
            correo.setComentarios("No tiene especificado su correo electronico.");
            correo.setEmail("<<No especificado>>");
         }
         correos.add(correo);
         responsables = responsablesIni;
         for (Responsable responsable : responsables) {
            if ("S".equals(responsable.getRecibeCopia())) {
               correo = new CorreoSolicitud(pasoNotifica.getFlujo().getClave(),
                       numeroSolicitud, numeroDetalle, ++contadorCorreos);
               Usuario usuario;
               if (responsable.getUsuario() == null) {
                  usuario = flujoServicio.getUsuario(responsable.getLlave().getClaveUsuario());
               } else {
                  usuario = responsable.getUsuario();
               }
               correo.setUsuario(usuario);
               correo.setUsuarioCreo(claveUsuarioCreo);
               if (usuario.getEmail() != null) {
                  correo.setEmail(usuario.getEmail());
                  try {
                     String asunto = "Solicitud # " + numeroSolicitud
                             + ", Paso: " + pasoNotifica.getDescripcionCorta();
                     String mensaje;
                     if ("RE".equals(tipoFlujo)) {
                        mensaje = generarMensajeReembolsoFin(usuario.getNombre(), pasoNotifica.getFlujo().getClave(),
                                pasoNotifica.getFlujo().getDescripcionCorta(),
                                numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                                solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);

                     } else {
                        mensaje = generarMensajeFin(usuario.getNombre(), pasoNotifica.getFlujo().getClave(),
                                pasoNotifica.getFlujo().getDescripcionCorta(),
                                numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                                solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);
                     }
                     emailServicio.enviarEmailHTML(usuario.getEmail(), asunto, mensaje);
                     correo.setEstatus("E");
                  } catch (Exception ex) {
                     correo.setEstatus("O");
                     correo.setComentarios(ex.getMessage());
                  }
               } else {
                  correo.setEstatus("O");
                  correo.setComentarios("No tiene especificado su correo electrónico.");
                  correo.setEmail("<<No especificado>>");
               }
               correo.setComentarios("COPIA");
               correos.add(correo);
            }
         }
      } else if ("M".equals(pasoNotifica.getTipo())) {
         responsables = pasoNotifica.getResponsables();
         for (Responsable responsable : responsables) {
            correo = new CorreoSolicitud(pasoNotifica.getFlujo().getClave(),
                    numeroSolicitud, numeroDetalle, ++contadorCorreos);
            Usuario usuario;
            if (responsable.getUsuario() == null) {
               usuario = flujoServicio.getUsuario(responsable.getLlave().getClaveUsuario());
            } else {
               usuario = responsable.getUsuario();
            }
            correo.setUsuario(usuario);
            correo.setUsuarioCreo(claveUsuarioCreo);
            if (usuario.getEmail() != null) {
               correo.setEmail(usuario.getEmail());
               try {
                  String asunto;
                  asunto = "Solicitud # " + numeroSolicitud
                          + ", Paso: " + pasoNotifica.getDescripcionCorta();
                  String mensaje;
                  if ("RE".equals(tipoFlujo)) {
                     mensaje = generarMensajeReembolso(usuario.getNombre(), pasoNotifica.getFlujo().getClave(), pasoNotifica.getFlujo().getDescripcionCorta(),
                             numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                             solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);

                  } else {
                     mensaje = generarMensaje(usuario.getNombre(), pasoNotifica.getFlujo().getClave(), pasoNotifica.getFlujo().getDescripcionCorta(),
                             numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                             solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);

                  }
                  emailServicio.enviarEmailHTML(usuario.getEmail(), asunto, mensaje);
                  correo.setEstatus("E");
                  if ("S".equals(responsable.getRecibeCopia())) {
                     correo.setComentarios("COPIA");
                  }
               } catch (Exception ex) {
                  correo.setEstatus("O");
                  if ("S".equals(responsable.getRecibeCopia())) {
                     correo.setComentarios("COPIA");
                  }
                  correo.setComentarios(ex.getMessage());
               }
            } else {
               correo.setEstatus("O");
               if ("S".equals(responsable.getRecibeCopia())) {
                  correo.setComentarios("COPIA");
               }
               correo.setComentarios("No tiene especificado su correo electrónico.");
               correo.setEmail("<<No especificado>>");
            }
            correos.add(correo);
         }
      } else if ("I".equals(pasoNotifica.getTipo())) {
         correo = new CorreoSolicitud(pasoNotifica.getFlujo().getClave(),
                 numeroSolicitud, numeroDetalle, ++contadorCorreos);
         correo.setUsuario(solicitante);
         correo.setUsuarioCreo(claveUsuarioCreo);
         if (solicitante.getEmail() != null) {
            correo.setEmail(solicitante.getEmail());
            try {
               String asunto = "Solicitud # " + numeroSolicitud
                       + " Correccion, Paso: " + pasoNotifica.getDescripcionCorta();
               String mensaje;
               if ("RE".equals(tipoFlujo)) {
                  mensaje = generarMensajeReembolso(solicitante.getNombre(), pasoNotifica.getFlujo().getClave(),
                          pasoNotifica.getFlujo().getDescripcionCorta(),
                          numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                          solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);

               } else {
                  mensaje = generarMensaje(solicitante.getNombre(), pasoNotifica.getFlujo().getClave(),
                          pasoNotifica.getFlujo().getDescripcionCorta(),
                          numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                          solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);
               }
               emailServicio.enviarEmailHTML(solicitante.getEmail(), asunto, mensaje);
               correo.setEstatus("E");
            } catch (Exception ex) {
               correo.setEstatus("O");
               correo.setComentarios(ex.getMessage());
            }
         } else {
            correo.setEstatus("O");
            correo.setComentarios("No tiene especificado su correo electronico.");
            correo.setEmail("<<No especificado>>");
         }
         correos.add(correo);
         responsables = responsablesIni;
         for (Responsable responsable : responsables) {
            if ("S".equals(responsable.getRecibeCopia())) {
               correo = new CorreoSolicitud(pasoNotifica.getFlujo().getClave(),
                       numeroSolicitud, numeroDetalle, ++contadorCorreos);
               Usuario usuario;
               if (responsable.getUsuario() == null) {
                  usuario = flujoServicio.getUsuario(responsable.getLlave().getClaveUsuario());
               } else {
                  usuario = responsable.getUsuario();
               }
               correo.setUsuario(usuario);
               correo.setUsuarioCreo(claveUsuarioCreo);
               if (usuario.getEmail() != null) {
                  correo.setEmail(usuario.getEmail());
                  try {
                     String asunto = "Solicitud # " + numeroSolicitud
                             + " Correccion, Paso: " + pasoNotifica.getDescripcionCorta();
                     String mensaje;
                     if ("RE".equals(tipoFlujo)) {
                        mensaje = generarMensajeReembolsoFin(usuario.getNombre(), pasoNotifica.getFlujo().getClave(),
                                pasoNotifica.getFlujo().getDescripcionCorta(),
                                numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                                solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);

                     } else {
                        mensaje = generarMensajeFin(usuario.getNombre(), pasoNotifica.getFlujo().getClave(),
                                pasoNotifica.getFlujo().getDescripcionCorta(),
                                numeroSolicitud, pasoNotifica.getLlave().getClavePaso() + "-" + pasoNotifica.getDescripcionCorta(),
                                solicitante.getNombre() + " " + solicitante.getApellidos(), fechaCreado, personasAprobaron);
                     }
                     emailServicio.enviarEmailHTML(usuario.getEmail(), asunto, mensaje);
                     correo.setEstatus("E");
                  } catch (Exception ex) {
                     correo.setEstatus("O");
                     correo.setComentarios(ex.getMessage());
                  }
               } else {
                  correo.setEstatus("O");
                  correo.setComentarios("No tiene especificado su correo electrónico.");
                  correo.setEmail("<<No especificado>>");
               }
               correo.setComentarios("COPIA");
               correos.add(correo);
            }
         }
      }
      return correos;
   }

   private String generarMensaje(String nombrePersona, String claveFlujo, String descripcionFlujo, int numeroSolictud, String paso,
           String solicitante, Date fecha, List<String> personasAprobaron) {
      java.text.SimpleDateFormat formateadorFecha = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
      String mensajeHTML = "<html><head><title>Mensaje aprobaci&oacute;n</title><style>"
              + "body { font: 13px Arial, Helvetica, sans-serif; color: #6d6d6d; background-color:#f0f0f0; }"
              + ".tbl_formulario td{padding: 3px;} .tbl_formulario th{text-align: right;} #pnl_foot{font-style: italic;font-size: 8pt;} "
              + ".tbl_aprobadores th{border-top: 1px solid black;} "
              + "</style></head><body><h3>Estimado/a " + nombrePersona + "</h3>"
              + "<p>Se le informa que tiene una solicitud pendiente para su revisi&oacute;n. <br/>"
              + "Los detalles son los siguientes:</p><br/>"
              + "<table class=\"tbl_formulario\"><tr><th>Flujo:</th><td>" + claveFlujo + "-" + descripcionFlujo
              + "</td><th>Solicitud N&deg;:</th><td>" + numeroSolictud + "</td></tr>"
              + "<tr><th>Paso:</th><td>" + paso + "</td><th>Solicitante:</th><td>" + solicitante + "</td></tr>"
              + "<tr><th>Creado:</th><td>" + formateadorFecha.format(fecha) + "</td><th></th><td></td></tr>"
              + "</table>";
      if (personasAprobaron != null && !personasAprobaron.isEmpty()) {
         int numeroPers = personasAprobaron.size();
         mensajeHTML += "<br/><table class='tbl_aprobadores'>"
                 + "<tr><td>" + solicitante + "</td><td>" + personasAprobaron.get(0) + "</td><td>"
                 + (numeroPers > 1 ? personasAprobaron.get(1) : "") + "</td><td>"
                 + (numeroPers > 2 ? personasAprobaron.get(2) : "") + "</td></tr>"
                 + "<tr><th>Cre&oacute;</th><th>Revis&oacute;</th><th>" + (numeroPers > 1 ? "Aprob&oacute;" : "") + "</th><th>" + (numeroPers > 2 ? "Aprob&oacute;" : "") + "</th></tr>"
                 + "</table>";
      }
      mensajeHTML += "<p>Para su aprobaci&oacute;n y m&aacute;s detalle del mismo, ingrese a la siguiente liga:<br/>"
              + "<a href='" + emailServicio.getUrlPagina() + claveFlujo + "&ns=" + numeroSolictud
              + "'>Solicitud N&deg;: " + numeroSolictud + "</a></p><br/><p id=\"pnl_foot\">Este es un correo generado autom&aacute;ticamente, favor de no responderlo.</p>"
              + "</body></html>";
      return mensajeHTML;
   }

   private String generarMensajeFin(String nombrePersona, String claveFlujo, String descripcionFlujo, int numeroSolictud, String paso,
           String solicitante, Date fecha, List<String> personasAprobaron) {
      java.text.SimpleDateFormat formateadorFecha = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
      String mensajeHTML = "<html><head><title>Mensaje finalizaci&oacute;n</title><style>"
              + "body { font: 13px Arial, Helvetica, sans-serif; color: #6d6d6d; background-color:#f0f0f0; }"
              + ".tbl_formulario td{padding: 3px;} .tbl_formulario th{text-align: right;} #pnl_foot{font-style: italic;font-size: 8pt;} "
              + ".tbl_aprobadores th{border-top: 1px solid black;} "
              + "</style></head><body><h3>Estimado/a " + nombrePersona + "</h3>"
              + "<p>Se le informa que la solicitud de aprobacion ha finalizado. <br/>"
              + "Los detalles son los siguientes:</p><br/>"
              + "<table class=\"tbl_formulario\"><tr><th>Flujo:</th><td>" + claveFlujo + "-" + descripcionFlujo
              + "</td><th>Solicitud N&deg;:</th><td>" + numeroSolictud + "</td></tr>"
              + "<tr><th>Paso:</th><td>" + paso + "</td><th>Solicitante:</th><td>" + solicitante + "</td></tr>"
              + "<tr><th>Creado:</th><td>" + formateadorFecha.format(fecha) + "</td><th></th><td></td></tr>"
              + "</table>";
      if (personasAprobaron != null && !personasAprobaron.isEmpty()) {
         int numeroPers = personasAprobaron.size();
         mensajeHTML += "<br/><table class='tbl_aprobadores'>"
                 + "<tr><td>" + solicitante + "</td><td>" + personasAprobaron.get(0) + "</td><td>"
                 + (numeroPers > 1 ? personasAprobaron.get(1) : "") + "</td><td>"
                 + (numeroPers > 2 ? personasAprobaron.get(2) : "") + "</td></tr>"
                 + "<tr><th>Cre&oacute;</th><th>Revis&oacute;</th><th>" + (numeroPers > 1 ? "Aprob&oacute;" : "") + "</th><th>" + (numeroPers > 2 ? "Aprob&oacute;" : "") + "</th></tr>"
                 + "</table>";
      }
      mensajeHTML += "<p>Para m&aacute;s detalle del mismo, ingrese a la siguiente liga:<br/>"
              + "<a href='" + emailServicio.getUrlPagina() + claveFlujo + "&ns=" + numeroSolictud
              + "'>Solicitud N&deg;: " + numeroSolictud + "</a></p><br/><p id=\"pnl_foot\">Este es un correo generado autom&aacute;ticamente, favor de no responderlo.</p>"
              + "</body></html>";
      return mensajeHTML;
   }

   private String generarMensajeReembolsoFin(String nombrePersona, String claveFlujo, String descripcionFlujo,
           int numeroSolictud, String paso, String solicitante, Date fecha, List<String> personasAprobaron) {
      java.text.SimpleDateFormat formateadorFecha = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
      String mensajeHTML = "<html><head><title>Mensaje finalizaci&oacute;n</title><style>"
              + "body { font: 13px Arial, Helvetica, sans-serif; color: #6d6d6d; background-color:#f0f0f0; }"
              + ".tbl_formulario td{padding: 3px;} .tbl_formulario th{text-align: right;} #pnl_foot{font-style: italic;font-size: 8pt;} "
              + ".tbl_aprobadores th{border-top: 1px solid black;} "
              + "</style></head><body><h3>Estimado/a " + nombrePersona + "</h3>"
              + "<p>Se le informa que la solicitud de Reembolso ha finalizado. <br/>"
              + "Los detalles son los siguientes:</p><br/>"
              + "<table class=\"tbl_formulario\"><tr><th>Flujo:</th><td>" + claveFlujo + "-" + descripcionFlujo
              + "</td><th>Solicitud N&deg;:</th><td>" + numeroSolictud + "</td></tr>"
              + "<tr><th>Paso:</th><td>" + paso + "</td><th>Solicitante:</th><td>" + solicitante + "</td></tr>"
              + "<tr><th>Creado:</th><td>" + formateadorFecha.format(fecha) + "</td><th></th><td></td></tr>"
              + "</table>";
      if (personasAprobaron != null && !personasAprobaron.isEmpty()) {
         int numeroPers = personasAprobaron.size();
         mensajeHTML += "<br/><table class='tbl_aprobadores'>"
                 + "<tr><td>" + personasAprobaron.get(0) + "</td><td>"
                 + (numeroPers > 1 ? personasAprobaron.get(1) : "") + "</td><td>"
                 + (numeroPers > 2 ? personasAprobaron.get(2) : "") + "</td><td>"
                 + (numeroPers > 3 ? personasAprobaron.get(3) : "") + "</td></tr>"
                 + "<tr><th>Cre&oacute;</th>"
                 + "<th>Revis&oacute;</th><th>"
                 + (numeroPers > 2 ? "Aprob&oacute;" : "") + "</th><th>"
                 + (numeroPers > 3 ? "Aprob&oacute;" : "") + "</th></tr>"
                 + "</table>";
      }
      mensajeHTML += "<p>Para m&aacute;s detalle del mismo, ingrese a la siguiente liga:<br/>"
              + "<a href='" + emailServicio.getUrlPagina() + claveFlujo + "&ns=" + numeroSolictud
              + "'>Solicitud N&deg;: " + numeroSolictud + "</a></p><br/><p id=\"pnl_foot\">Este es un correo generado autom&aacute;ticamente, favor de no responderlo.</p>"
              + "</body></html>";
      return mensajeHTML;
   }

   private String generarMensajeReembolso(String nombrePersona, String claveFlujo, String descripcionFlujo,
           int numeroSolictud, String paso, String solicitante, Date fecha, List<String> personasAprobaron) {
      java.text.SimpleDateFormat formateadorFecha = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
      String mensajeHTML = "<html><head><title>Mensaje aprobaci&oacute;n</title><style>"
              + "body { font: 13px Arial, Helvetica, sans-serif; color: #6d6d6d; background-color:#f0f0f0; }"
              + ".tbl_formulario td{padding: 3px;} .tbl_formulario th{text-align: right;} #pnl_foot{font-style: italic;font-size: 8pt;} "
              + ".tbl_aprobadores th{border-top: 1px solid black;} "
              + "</style></head><body><h3>Estimado/a " + nombrePersona + "</h3>"
              + "<p>Se le informa que tiene un Reembolso pendiente para su revisi&oacute;n. <br/>"
              + "Los detalles son los siguientes:</p><br/>"
              + "<table class=\"tbl_formulario\"><tr><th>Flujo:</th><td>" + claveFlujo + "-" + descripcionFlujo
              + "</td><th>Solicitud N&deg;:</th><td>" + numeroSolictud + "</td></tr>"
              + "<tr><th>Paso:</th><td>" + paso + "</td><th>Solicitante:</th><td>" + solicitante + "</td></tr>"
              + "<tr><th>Creado:</th><td>" + formateadorFecha.format(fecha) + "</td><th></th><td></td></tr>"
              + "</table>";
      if (personasAprobaron != null && !personasAprobaron.isEmpty()) {
         int numeroPers = personasAprobaron.size();
         mensajeHTML += "<br/><table class='tbl_aprobadores'>"
                 + "<tr><td>" + personasAprobaron.get(0) + "</td><td>"
                 + (numeroPers > 1 ? personasAprobaron.get(1) : "") + "</td><td>"
                 + (numeroPers > 2 ? personasAprobaron.get(2) : "") + "</td><td>"
                 + (numeroPers > 3 ? personasAprobaron.get(3) : "") + "</td></tr>"
                 + "<tr><th>Cre&oacute;</th>"
                 + "<th>Revis&oacute;</th><th>"
                 + (numeroPers > 2 ? "Aprob&oacute;" : "") + "</th><th>"
                 + (numeroPers > 3 ? "Aprob&oacute;" : "") + "</th></tr>"
                 + "</table>";
      }
      mensajeHTML += "<p>Para su aprobaci&oacute;n y m&aacute;s detalle del mismo, ingrese a la siguiente liga:<br/>"
              + "<a href='" + emailServicio.getUrlPagina() + claveFlujo + "&ns=" + numeroSolictud
              + "'>Solicitud N&deg;: " + numeroSolictud + "</a></p><br/><p id=\"pnl_foot\">Este es un correo generado autom&aacute;ticamente, favor de no responderlo.</p>"
              + "</body></html>";
      return mensajeHTML;
   }

   public Usuario getUsuario(String usuarioActual) {
      return flujoServicio.getUsuario(usuarioActual);
   }

   public List<Flujo> getFlujo(String usuarioActual, String tipoFlujo) {
      return flujoServicio.obtenerFlujos(usuarioActual, tipoFlujo);
   }
}
